#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include "InetAddr.hpp"
#include"ThreadPool.hpp"
#include"LockGuard.hpp"
#include"Log.hpp"

using task_t = std::function<void()>;
class Route
{
public:
    Route()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }
    void CheckOnlineUser(InetAddr &who)
    {
        LockGuard lockguard(&_mutex);
        for (auto &user : _online_user)
        {
            if (user == who)
            {
                return;
            }
        }
        _online_user.push_back(who);
    }
    void Offline(InetAddr &who)
    {
        LockGuard lockguard(&_mutex);
        auto it = _online_user.begin();
        while (it != _online_user.end())
        {
            LOG(DEBUG,"offline \n");
            if (*it == who)
            {
                LOG(DEBUG, "%s is offline\n", who.AddrStr().c_str());
                _online_user.erase(it);
                break;
            }
            it++;
        }
    }
    void ForwardHelper(int sockfd,const std::string message,InetAddr who)
    {
        LockGuard lockguard(&_mutex);
        std::string send_message="["+who.AddrStr()+" ]#"+message;
        for(auto &user:_online_user)
        {
            struct sockaddr_in peer=user.Addr();
            ::sendto(sockfd,send_message.c_str(),send_message.size(),0,(struct sockaddr*)&peer,sizeof(peer));
        }
    }
    void Forward(int sockfd,const std::string &message,InetAddr &who)
    {
        // 1:检查用户是否存在 
        CheckOnlineUser(who);
        if(message=="QUIT"||message=="Q")
        {
            Offline(who);
        }
        task_t t=std::bind(&Route::ForwardHelper,this,sockfd,message,who);
        ThreadPool<task_t>::GetInstance()->Equeue(t);
    }
    ~Route()
    {
        pthread_mutex_destroy(&_mutex);
    }

private:
    pthread_mutex_t _mutex;
    std::vector<InetAddr> _online_user;
};
